#include "TcpDataPacket.h"
#include <boost/asio.hpp>

using namespace clusnet::net;

TcpDataPacket::TcpDataPacket(size_t bodyLength)
    : bodyLength_(bodyLength),
      data_(headerLength_ + bodyLength)
{
}

TcpDataPacket::TcpDataPacket(clusnet::base::DynamicBuffer& data, size_t bodyLength)
    : bodyLength_(bodyLength),
      data_(data)
{
}

TcpDataPacket::TcpDataPacket(clusnet::base::DynamicBuffer&& data, size_t bodyLength)
    : bodyLength_(bodyLength),
      data_(std::move(data))
{
}

TcpDataPacket::TcpDataPacket(const TcpDataPacket& that)
    : bodyLength_(that.bodyLength_),
      data_(that.data_)
{
}

TcpDataPacket::~TcpDataPacket()
{
}

TcpDataPacket::TcpDataPacket(TcpDataPacket&& that)
    : bodyLength_(that.bodyLength_),
      data_(std::move(that.data_))
{
    that.bodyLength_ = 0;
}

TcpDataPacket& TcpDataPacket::operator= (TcpDataPacket&& that)
{
    if (this == &that)
    {
        return *this;
    }

    data_ = std::move(that.data_);
    bodyLength_ = that.bodyLength_;
    that.bodyLength_ = 0;
    return *this;
}

void TcpDataPacket::reset(size_t bodyLength)
{
    bodyLength_ = bodyLength;
    data_.resize(dataLength()); 
    data_.bzero();
}

void TcpDataPacket::setBodyLength(size_t length)
{
    if (length > bodyLength_)
    {
        data_.resize(headerLength_ + length);
    }
    bodyLength_ = length;
}

void TcpDataPacket::decodeHeader()
{
    setBodyLength(ntohl(*(reinterpret_cast<size_t *>(header()))));
}

void TcpDataPacket::encodeHeader()
{
    size_t len = htonl(bodyLength_);
    std::memcpy(header(), &len, headerLength_);
}

TcpDataPacketStream::TcpDataPacketStream()
{
    std::string header(TcpDataPacket::headerLength(), '0');
    data_.append(header.c_str(), header.length());
}

void TcpDataPacketStream::append(const char* data, size_t len)
{
    data_.append(data, len);
}

TcpDataPacket TcpDataPacketStream::data() &
{
    return TcpDataPacket(data_, data_.length() - TcpDataPacket::headerLength());
}

TcpDataPacket TcpDataPacketStream::data() &&
{
    size_t bodyLength = data_.length() - TcpDataPacket::headerLength();
    TcpDataPacket packet(std::move(data_), bodyLength);
    packet.encodeHeader();
    return packet;
}
